package com.cmwa.scbp.base.mvc.controller;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.cmwa.scbp.base.constants.Constant;


@Controller
@RequestMapping("/captcha")
public class CaptchaController {

	/**
	 * 验证码个数
	 */
	private final int captchaLength = 4;
	/**
	 * 字符大小
	 */
	private final int wordSize = 24;
	/**
	 * 图片宽度
	 */
	private final int width = 105;
	/**
	 * 图片高度
	 */
	private final int height = 44;
	/**
	 * 线宽
	 */
	private final int lineWidth = 2;
	/**
	 * 干扰线条数
	 */
	private final int count = 200;
	
	@RequestMapping("/get")
	public void get(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 设置页面不缓存
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "No-cache");
		response.setDateHeader("Expires", 0);
		// 在内存中创建图像
		final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		// 获取图像上下文
		final Graphics2D graphics = (Graphics2D) image.getGraphics();
		// 设置背景颜色
		graphics.setColor(Color.WHITE);
		// 填充衍射
		graphics.fillRect(0, 0, width, height);
		// 设定边框颜色
		graphics.drawRect(0, 0, width - 1, height - 1);
		
		final Random random = new Random();
		
		// 生成干扰线
		for(int i = 0; i < count; i++) {
			graphics.setColor(getRandColor(150, 200));
			// 保证画在边框内
			final int x = random.nextInt(width - lineWidth - 1) + 1;
			final int y = random.nextInt(height - lineWidth - 1) + 1;
			final int xl = random.nextInt(lineWidth);
			final int yl = random.nextInt(lineWidth);
			graphics.drawLine(x, y, x + xl, y + yl);
		}
		
		// 生成随机数
		final String resultCode = extractRandCode();
		for(int i = 0; i < resultCode.length(); i++) {
			// 设置字体颜色
			graphics.setColor(Color.BLACK);
			// 设置字体样式
			graphics.setFont(new Font("Arial Black", Font.BOLD, wordSize));  // Times New Roman
			// 设置字符边距
			graphics.drawString(String.valueOf(resultCode.charAt(i)), (23 * i) + 8, 31);
		}
		// 写入session
		request.getSession().setAttribute(Constant.CAPTCHA, resultCode);
		// 使图象生效
		graphics.dispose();
		// 输入到页面
		ImageIO.write(image, "JPEG", response.getOutputStream());
	}

	/**
	 * 生成随机码
	 * @author ex-hejm
	 * @date 2018年10月25日 下午6:56:55
	 * @return
	 */
	private String extractRandCode() {
		return RandCodeImageEnum.NUMBER_CHAR.generateStr(captchaLength);
	}

	/**
	 * 根据给定的数字生成不同的颜色
	 * @author ex-hejm
	 * @date 2018年10月25日 下午6:58:42
	 * @param i
	 * @param j
	 * @return
	 */
	private Color getRandColor(int i, int j) {
		final Random random = new Random();
		if(i > 255) {
			i = 255;
		}
		if(j > 255) {
			j = 255;
		}
		final int r = i + random.nextInt(j - i);
		final int g = i + random.nextInt(j - i);
		final int b = i + random.nextInt(j - i);
		return new Color(r, g, b);
	}
	
	/**
	 * 验证码样式
	 * @author ex-hejm
	 * @date 2018年10月25日 下午7:00:38
	 */
	enum RandCodeImageEnum {
		/**
		 * 混合字符串，去除0、1、o、O、I、l这几个坑人的字符，只会让人看不清
		 */
		NUMBER_CHAR("2346789abcdefghijkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ"),
		/**
		 * 字符串
		 */
		JUST_CHAR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
		/**
		 * 小写字母
		 */
		SMALL_CHAR("abcdefghijklmnopqrstuvwxyz"),
		/**
		 * 数字
		 */
		NUMBER("0123456789"),
		/**
		 * 大写字母
		 */
		BIG_CHAR("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
		
		private String str;
		
		private RandCodeImageEnum(final String charStr) {
			this.str = charStr;
		}
		/**
		 * 生成随机码
		 * @author ex-hejm
		 * @date 2018年10月25日 下午7:07:23
		 * @param codeLength
		 * @return
		 */
		public String generateStr(final int codeLength) {
			final StringBuilder sb = new StringBuilder();
			final Random random = new Random();
			final String sourceStr = getCharStr();
			
			for(int i = 0; i < codeLength; i++) {
				sb.append(sourceStr.charAt(random.nextInt(sourceStr.length())));
			}
			return sb.toString();
		}
		
		public String getCharStr() {
			return str;
		}
	}
	
}
